# 参考：https://stackoverflow.com/questions/16056793/python-win32com-client-dispatch-looping-through-word-documents-and-export-to-pdf

import threading
import os
import os.path
from win32com import client as wc
import pythoncom
import PySimpleGUI as sg

# basename: test.txt
# filename: test
# suffix: .txt
def get_names(src_folder_path, src_ext='.ppt', new_ext ='.pptx', target_folder_path=None):
    basenames = [name for name in os.listdir(src_folder_path)
             if os.path.isfile(os.path.join(src_folder_path, name)) and name.endswith(src_ext)]
    filenames = [os.path.splitext(basename)[0] for basename in basenames]
    # 老文件名路径，含扩展名
    oldnames_fullpath = [os.path.join(src_folder_path, name) for name in basenames]
    # 老文件名路径，不含扩展名
    oldnames_fullpath_withoutext = [os.path.splitext(oldname_path)[0] for oldname_path in oldnames_fullpath]

    # 新文件名路径，含扩展名
    if target_folder_path is None or target_folder_path=='':
        newnames_fullpath = [name_without_ext + new_ext for name_without_ext in oldnames_fullpath_withoutext]
    else:
        # 如果目标路径不是以反斜杠结尾，则加上反斜杠
        if not target_folder_path.endswith('\\'):
            target_folder_path = target_folder_path + '\\'
        newnames_fullpath = [os.path.join(target_folder_path, name) + new_ext for name in filenames]

    # 总文件数
    cnt = len(oldnames_fullpath)
    # 新旧文件对
    old_new_pair = zip(oldnames_fullpath, newnames_fullpath)
    return old_new_pair, cnt

def TransBatch(src_folder_path, window, out_format_number = 11, src_ext='.ppt', new_ext='.pptx', target_folder_path=None):
    # 源格式和目标格式相同时，不执行转换
    if (src_ext == new_ext):
        window.write_event_value('-NOTHING-', '')
        return
    # Get all regular files
    old_new_pairs, total_cnt = get_names(src_folder_path, src_ext, new_ext, target_folder_path)
    # for pair in old_new_pairs:
    #     print(pair[0], pair[1])

    pythoncom.CoInitialize() #多线程中需要调用CoInitialize()方法，非多线程不需要
    powerpoint = wc.DispatchEx('Powerpoint.Application')
    for index, pair in enumerate(old_new_pairs):
        old_file, new_file = pair[0], pair[1]
        print(old_file, new_file)
        # 打开 旧word 文件
        doc = powerpoint.Presentations.Open(old_file, WithWindow=False)
        # 保存为 调用SaveAS时会自动添加扩展名
        doc.SaveAs(new_file, out_format_number)
        # 关闭word文档
        doc.Close()
        # print(f"{docxName} 生成完毕！")
        # 发送事件，用于更新UI
        window.write_event_value('-Part_DONE-', f"第{index+1}/{total_cnt}个文件生成完毕！")
    powerpoint.Quit()
    pythoncom.CoUninitialize()
    window.write_event_value('-DONE-', '')

if __name__ == "__main__":
    # 原始文件的后缀（扩展名）
    src_dict ={'Radio_PPT':'.ppt', 'Radio_PPTX': '.pptx'}
    # pdf对应ppSaveAsPDF,ppt对应ppSaveAsPresentation,pptx对应ppSaveAsDefault
    # 输出格式，必须使用代码表示, 参考：https://docs.microsoft.com/en-us/office/vba/api/powerpoint.ppsaveasfiletype
    format_dict = {}
    format_dict.update({'pptx': {'ext': '.pptx', 'formatType': 11}})
    format_dict.update({'ppt': {'ext': '.ppt', 'formatType': 1}})
    format_dict.update({'pdf': {'ext': '.pdf', 'formatType': 32}})
    format_dict.update({'jpg': {'ext': '.jpg', 'formatType': 17}})

    src_ext = '.ppt' #默认原始文件扩展名为.ppt
    new_ext = '.pptx'
    out_format_number = 11 #默认目标格式为pptx，代码为11
    target_folder_path=None

    sg.theme('DefaultNoMoreNagging')

    layout = [[sg.Text('请输入文件夹名称（包含ppt或pptx文档）', font=('Helvetica', 11))],
              [sg.Input(key='-IN-'), sg.Button('开始转换', key='Convert')],
              [sg.Text('原始格式：', font=('Helvetica', 9), justification='left'),
               sg.Radio('PPT', 'SRC', key='Radio_PPT', default=True, enable_events=True, size=(10, 1)),
               sg.Radio('PPTX', 'SRC', key='Radio_PPTX', enable_events=True, size=(10, 1))],
              [sg.Text('目标格式：', font=('Helvetica', 9), justification='left'),
               sg.Radio('TO PPTX', 'FORMAT', key='pptx', default=True, enable_events=True, size=(10, 1)),
               sg.Radio('TO PDF', 'FORMAT', key='pdf', enable_events=True, size=(10, 1)),
               sg.Radio('TO PPT', 'FORMAT', key='ppt', enable_events=True, size=(10, 1)),
               sg.Radio('TO JPG', 'FORMAT', key='jpg', enable_events=True, size=(10, 1))
               ],
              [sg.Text('输出文件夹：', font=('Helvetica', 9), tooltip='默认输出文件夹与输入相同', justification='left'), sg.Input(key='-target-')],
              [sg.Text(key='-OUT-')]
             ]

    window = sg.Window('powerpoint文件批量转换器', layout)
    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED:
            break
        elif event in ['Radio_PPT','Radio_PPTX']:
            src_ext = src_dict[event]
        elif event in ['pptx', 'pdf', 'ppt', 'jpg']: #点击了目标格式Radio触发该事件
            out_format_number = format_dict[event]['formatType']
            new_ext = format_dict[event]['ext']
        elif event == 'Convert':
            folder_path = values['-IN-']
            if len(folder_path) == 0:
                sg.popup('温馨提示', '请输入文件夹名称', values['-IN-'])
            else:
                target_folder_path = values['-target-'] if len(values['-target-'])>0 else None
                threading.Thread(target=TransBatch, args=(folder_path, window, out_format_number, src_ext, new_ext, target_folder_path, ), daemon=True).start()
                # 转换结束之前，按钮不可用
                window['Convert'].update(disabled=True)
                window['-OUT-'].update('开始转换......')
        elif event == '-DONE-':
            window['-OUT-'].update('转换完毕！')
            # 转换结束，按钮可用
            window['Convert'].update(disabled=False)
            window.refresh()
        elif event=='-NOTHING-':
            # print(event)
            window['-OUT-'].update('目标格式和源格式相同，什么都不干！')
            # 转换结束，按钮可用
            window['Convert'].update(disabled=False)
            window.refresh()
        elif event=='-Part_DONE-':
            window['-OUT-'].update(values[event])
            window.refresh()
        # print(values)
    window.close()

